<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
  <title>实例操作- 手风琴</title>
  <style type="text/css">
  * {
    padding: 0;
    margin: 0;
    box-sizing: content-box;
  }
  body {
    padding: 30px;
  }
  .slide {
    width: 300px;
    display: flex;
    flex-direction: column;
    /* box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); */
  }
  .slide dt {
    height: 30px;
    background: #34495e;
    color: white;
    display: flex;
    align-items: center;
    padding-left: 10px;
    cursor: pointer;
  }
  .slide dt:first-of-type {
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
  }
  .slide dd {
    height: 100px;
    background: #f1c40f;
    overflow: hidden;
  }
  .slide dd div {
    padding: 10px;
  }
  .slide dd:last-of-type {
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
  }
</style>
</head>
<body>
  <div class="container">
    <h1>实例操作- 手风琴</h1>
  </div>

  <div class="slide s1">
    <dt>后盾人</dt>
    <dd>
      <div>houdunren.com</div>
    </dd>
    <dt>后盾CMS</dt>
    <dd>
      <div>hdcms1.com</div>
    </dd>
    <dt>百度</dt>
    <dd>
      <div>baidu.com</div>
    </dd>
    <dt>腾讯</dt>
    <dd>
      <div>qq.com</div>
    </dd>
  </div>
  <script type="text/javascript">
  class Animation {
    constructor(el, opts) {
      var defaults = {
        timeout: 20,
        step: 2,
        // 默认显示状态
        isShow : 1,  // -1:隐藏状态 0:运动状态 1:显示状态

      }

      if(typeof el === 'object' && el.hasOwnProperty('el')) {
        this.opttions = Object.assign({}, defaults,  el, opts || {})
        el = el.el
        el instanceof Element || (el = document.querySelector(el))
      } else {
        this.opttions = Object.assign({}, defaults, opts || {})
      }
        
      this.el = el
      this.defaultHeight = parseInt(window.getComputedStyle(this.el, false).height)
      this._height = this.defaultHeight
    }

     // 通过访问属性简化操作
    set height(height) {
      this.el.style.height = height + 'px'
      this._height = height
    }
    get height() {
      return this._height
    }
    show(callback) {
      console.log('Animation show')
      this.isShow = 0
      let id = setInterval(()=> {
        this.height += this.opttions.step
        if(this.height >= this.defaultHeight) {
          clearInterval(id)
          this.isShow = 1 
          callback && callback();
          console.log(this.el.style.height, this.height, this._height)
          return 
        }
      }, this.opttions.timeout)
    }
   
    hide(callback) {
      console.log('Animation hide')
      this.isShow = 0
      let id = setInterval(() => {
        this.height -= this.opttions.step
        if(this.height <= 0) {
          clearInterval(id)
          this.isShow = -1 
          callback && callback();
          console.log(this.el.style.height, this.height, this._height)
          return 
        }
      }, this.opttions.timeout)
    }
  }  

  // Slide 点击进行切换的控制
  class Slide {
    constructor(el) {
      this.el = document.querySelector(el)
      this.links = this.el.querySelectorAll('dt')
      this.panels = [].map.call(this.el.querySelectorAll('dd'), (item, index) => {
        return new Pannel(item);
      })
    
      this.bind()
    }

    bind() {
      var self = this
      this.links.forEach((item, i) => {
        item.addEventListener('click', function() {
          self.action(i)
        })
      })
    }

    action(idx) {
      // 将其余的面板进行隐藏， 将当前的面板进行显示处理， 建立一个面板类 处理该逻辑 Pannel
      console.log('action ' + idx, this)
      

      // hideAll, show两个动画同时进行 show一下子就执行完了，hide需要执行的时间偏长，没有立马执行完
      // 需要等到hide执行完了 在执行show 队列 排队。。。。。
      
      // Pannel.hideAll(this.panels)
      // this.panels[idx].show(() => {
      //   console.log('sdfsfsdf')
        
      // })
      
      // 利用回调形成 动画队列
      Pannel.hideAll(Pannel.filter(this.panels, idx), () => {
        console.log('sdfsfsdf 全部成功完成后的回调')
        // 所有动画隐藏完毕了
        this.panels[idx].show(() => {
          console.log('展示页展示完成了')
        })
      })
      
    }
  }


  // 面板需要 进行显示/隐藏的动画操作 需要继承 Animation 动画类
  class Pannel extends Animation {
    static num = 0
    static hideAll(items, callback) {
      // 大于 表示现在有动画正在进行时
      if(this.num > 0) return ;
      items.forEach(item => {
        item.hide(() => {
          // hide 执行完成后的回掉
          if(++this.num === items.length) {
            this.num = 0 ;// 重新归零 表示可以再次执行动画
            callback && callback()  // 全部成功完成后的回调
          }
        })
      })
    }

    static filter(items, idx) {
      return items.filter((item,index) => index !== idx)
    }
  }
  var slide =  new Slide('.s1')

  </script>
</body>
</html>